<?php
class NerdPass_Auth implements Zend_Auth_Adapter_Interface {
	private $username;
	private $otp;
	private $password;
	
	public function __construct($username, $password, $otp) {
		$this->username = $username;
		$this->otp = $otp;
		$this->password = $password;
	}
	
	public function authenticate() {
		/* Get info required from database */
		$user = NerdPass_Data::getUser($this->username);
		if (!$user) {
			NerdPass_Data::$log->warn("Attempted to login with unknown identity, \"" . $this->username . '"');
			return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, $this->username, array("Invalid login"));
		}
		
		/* Verify token id belongs to user */
		$tid = substr($this->otp, 0, 12);
		if (md5($tid) != $user['tokenid']) {
			NerdPass_Data::$log->warn("Username '" . $this->username . "' used an incorrect key. Tokenid mismatch.");
			return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS, $this->username, array("Invalid login"));
		}
		
		/* Validate password */
		$nsec = new NerdPass_Secure($this->password, $this->username);
		if (!preg_match('|^(' . preg_quote($this->username) . ')(.*)|', $nsec->decrypt($user['keytest']), $matches)) {
			NerdPass_Data::$log->warn("Password provided for user '" . $this->username . "' did not pass the test.");
			return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, $this->username, array("Invalid login"));
		}
		else {
			// Save key in session for encryption and decryption
			$key_namespace = new Zend_Session_Namespace('keys');
			$key_namespace->key = $matches[2];
		}
		
		/* Validate OTP */
		$token = new Yubikey((int) $user['apiid'], $user['signaturekey']);
		$token->setCurlTimeout(20);
		$token->setTimestampTolerance(500);
		
		if ($token->verify(strtolower($this->otp))) {
			define('NERD_PASS_YBK', $token->getLastResponse());
			NerdPass_Data::$log->info("'" . $this->username . "' Logged in succesfully.");
			return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->username, array("Welcome to NerdPass"));
		}
		else {
			define('NERD_PASS_YBK', $token->getLastResponse());
			NerdPass_Data::$log->warn("Failed to authenticate the OTP with the server. Error Message: " . NERD_PASS_YBK);
			return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, $this->username, array("Invalid login"));
		}
	}
}